/*
 * Last edited: 06/07/13 by Ching-Ting
 */
package View;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import Model.Conference;
import Model.Controller;
import Model.Paper;
import View.ViewReview;

/**
 * This tab shows all submitted papers to specific conferences as well as provide
 * functions to edit, unsubmit and see reviews of a single paper.
 * 
 * @author 
 * @version UWTCSS 360, Spring 2013. 3-squared-software-systems.
 */
public class SubmittedPapers extends JPanel{

	private static final long serialVersionUID = 3241462484714623788L;
	private Controller controller;
	private ScrollPane scroll;
	private JLabel revision;
	private JLabel decision;

	/**
	 * Initialize fields.
	 * 
	 * @param control is the Controller from Model package.
	 * @author Ching-Ting Huang
	 */
	public SubmittedPapers(Controller control) {
		controller = control;
		scroll = new ScrollPane(controller, "auth");
		revision = new JLabel("(Select a manuscript to see the revision deadline: YYYY/MM/DD)");
		decision = new JLabel("(Select a manuscript to see the decision date: YYYY/MM/DD)");
		setup();
	} //SubmittedPapers

	/**
	 * Sets up the basic look and catch selection change from JTable in JScrollPane
	 * by utilizing propertyChangeListener.
	 * 
	 * @author Ching-Ting Huang
	 */
	private void setup() {
		final JLabel flag = new JLabel("auth");

		/*
		  Using property change listener to catch list selection changes in ScrollPane.
		  By passing in JLabel to ScrollPane, if setText is changed, JLabels on 
		  Conferences tab will change accordingly.
		 */
		flag.addPropertyChangeListener(new PropertyChangeListener(){
			@Override
			public void propertyChange(PropertyChangeEvent e) {
				if (e.getSource() == flag) {
					Object[] data = scroll.getRow(scroll.getSelectedRowNum());

					for (Conference conf : controller.getConferenceList()) {
						if (conf.getConferenceName().equals(data[1])) {
							int rev_day = conf.getPaperRevisionSubmissionDeadline().getDateDay();
							int rev_month = conf.getPaperRevisionSubmissionDeadline().getDateMonth();
							int rev_year = conf.getPaperRevisionSubmissionDeadline().getDateYear();
							revision.setText(rev_year + "/" + rev_month + "/" + rev_day);

							int app_day = conf.getNotifyAuthorsDeadline().getDateDay();
							int app_month = conf.getNotifyAuthorsDeadline().getDateMonth();
							int app_year = conf.getNotifyAuthorsDeadline().getDateYear();
							decision.setText(app_year + "/" + app_month + "/" + app_day);
						}
					}
				}
			} //propertyChange
		});

		scroll.setFlag(flag);
		JScrollPane pane = scroll.getScrollPane();
		pane.setWheelScrollingEnabled(true);

		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		add(pane);
		add(revisionComp());
		add(decisionComp());
		add(btns());
	} //setup

	/**
	 * Formatting the buttons and labels to a certain look using FlowLayout.
	 * 
	 * @return the Container containing both label and button.
	 * @author Ching-Ting Huang
	 */
	private Container revisionComp() {
		Container flow = new JPanel(new FlowLayout(FlowLayout.CENTER));
		JLabel lbl = new JLabel("Revision Deadline: ");
		flow.add(lbl);
		flow.add(revision);
		return flow;
	} //revisionComp

	/**
	 * Formatting the buttons and labels to a certain look using FlowLayout.
	 * 
	 * @return the Container containing both label and button.
	 * @author Ching-Ting Huang
	 */
	private Container decisionComp() {
		Container flow = new JPanel(new FlowLayout(FlowLayout.CENTER));
		JLabel lbl = new JLabel("Decision Date: ");
		flow.add(lbl);
		flow.add(decision);
		return flow;
	} //decisionComp

	/**
	 * Formatting the buttons to a certain look using FlowLayout as well as setting
	 * up their actionListener functionality when the buttons are clicked.
	 * 
	 * @return the Container containing the buttons.
	 * @author Ching-Ting Huang
	 */
	private Container btns() {
		Container contain = new JPanel(new FlowLayout(FlowLayout.CENTER));
		final JButton revise = new JButton("Edit Manuscript");
		final JButton download = new JButton("Download Manuscript");
		final JButton reviews = new JButton("See Reviews");
		final JButton unsubmit = new JButton("Unsubmit Manuscript");		
		
		revise.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getSource() == revise) {
					byte[] text = new byte[]{};

					if (scroll.getSelectedRowNum() != -1) {
						Object[] selected = scroll.getRow(scroll.getSelectedRowNum());
						Paper chosen = (Paper) selected[3];
						Paper paper = null;
						for (int i = 0; i < controller.getUserSubmittedPapers().size(); i++) {
							if (chosen.getUniqueCode() == controller.getUserSubmittedPapers().get(i).getUniqueCode()) {
								paper = controller.getUserSubmittedPapers().get(i);
							}
						}
						Edit edit = new Edit((JFrame) SwingUtilities.windowForComponent(revise),
								"Edit Manuscript", paper);
						edit.start(text);

					} else if (scroll.getSelectedRowNum() == -1) {
						JOptionPane.showMessageDialog(null, "Please select a manuscript to edit.",
								"Select Manuscript", JOptionPane.WARNING_MESSAGE);
					}
				}
			} //actionPerformed
		});
		
		download.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getSource() == download) {
					if (scroll.getSelectedRowNum() != -1) {
						Object[] selected = scroll.getRow(scroll.getSelectedRowNum());
						Paper chosen = (Paper)selected[3];
						Paper paper = null;
						for (int i = 0; i < controller.getUserSubmittedPapers().size(); i++) {
							if (chosen.getUniqueCode() == controller.getUserSubmittedPapers().get(i).getUniqueCode()) {
								paper = controller.getUserSubmittedPapers().get(i);
							}
						}
						Save save = new Save((JFrame) SwingUtilities.windowForComponent(download),
								"Save Manuscript", paper);
						save.start();

					} else if (scroll.getSelectedRowNum() == -1) {
						JOptionPane.showMessageDialog(null, "Please select a manuscript to save.",
								"Save Manuscript", JOptionPane.WARNING_MESSAGE);
					}
					
					
				}
			} //actionPerformed
		});

		reviews.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getSource() == reviews) {
					if (scroll.getSelectedRowNum() != -1) {
						Object[] selected = scroll.getRow(scroll.getSelectedRowNum());
						Paper chosen = (Paper)selected[3];
						Paper paper = null;
						for (int i = 0; i < controller.getUserSubmittedPapers().size(); i++) {
							if (chosen.getUniqueCode() == controller.getUserSubmittedPapers().get(i).getUniqueCode()) {
								paper = controller.getUserSubmittedPapers().get(i);
							}
						}
						
						final int acceptedStatus = paper.getAcceptedStatus();
						if (acceptedStatus == 0) {
							JOptionPane.showMessageDialog(null, "Review for " + paper.getTitle() + " is not ready for viewing yet.",
									"Reviews not ready", JOptionPane.WARNING_MESSAGE);
						} else {
							new ViewReview(paper);
						}

					} else if (scroll.getSelectedRowNum() == -1) {
						JOptionPane.showMessageDialog(null, "Please select a manuscript to view reviews.",
								"Select Manuscript", JOptionPane.WARNING_MESSAGE);
					}
				}
			} //actionPerformed
		});

		//Edited by Daniel
		unsubmit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getSource() == unsubmit) {
					String title = null;
					int index = -1;

					int row = scroll.getSelectedRowNum();
					if (row == -1) {
						JOptionPane.showMessageDialog(null, "Please select a manuscript to unsubmit.",
								"Select Manuscript", JOptionPane.WARNING_MESSAGE);
					} else {
						Object[] selected = scroll.getRow(row);
						Paper thisPaper = (Paper)selected[3];
						for (int i = 0; i < controller.getUserSubmittedPapers().size(); i++) {                                                           // This is not the right way to unsubmit a paper, the Controller method needs to be used (deletePaper())
							if (thisPaper.getUniqueCode() == controller.getUserSubmittedPapers().get(i).getUniqueCode()) {
								title = controller.getCurrentUser().getAuthorPapers().get(i).getTitle();
								index = i;
							}
						}

						int result = JOptionPane.showConfirmDialog(null, 
								"Are you sure you want to unsubmit this manuscript : " + title + " ?", 
								"Unsubmit Manuscript", 
								JOptionPane.YES_NO_OPTION);

						if (result == JOptionPane.YES_OPTION) {
							scroll.removeFromTable(index);
							controller.deletePaper(thisPaper);
						}
					}
				}
			} //actionPerformed
		});

		contain.add(revise);
		contain.add(download);
		contain.add(reviews);
		contain.add(unsubmit);
		return contain;
	} //btns

	/**
	 * Used to print out title for tabbed panes.
	 * 
	 * @author Ching-Ting Huang
	 */
	public String getName() {
		return "Submitted Papers";
	} //getName



	//==================== Inner Class: Edit ==========================//

	/**
	 * This class is  JDialog containing an editable text field for the user to 
	 * edit their paper along with minimal information about their paper on the
	 * side.
	 * 
	 * @author Ching-Ting Huang
	 * @version UWTCSS 360, Spring 2013. 3-squared-software-systems.
	 */
	private class Edit extends JDialog {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1869065425026869471L;
		private JLabel words;
		private JLabel revdate;
		private JTextArea area;
		private Paper paper;
		private byte[] text;
		private String content;

		/**
		 * Initialize the fields.
		 * 
		 * @param frame is the frame this JDialog will center on.
		 * @param title is the title for the JDialog.
		 * @param p is the paper currently selected.
		 */
		private Edit(JFrame frame, String title, Paper p) {
			super(frame, title);
			paper = p;
			try {
				content = new String(paper.loadDigitalPaper(), "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			setup();
		} //Edit

		/**
		 * Sets up the basic layout of the JDialog and calling other methods to
		 * fulfill more functionality of their component.
		 */
		private void setup() {
			JPanel main = new JPanel();
			JPanel grid = new JPanel();
			JTextArea txt = displayContent();
			Container btns = buttons();
			JPanel labels = labels(btns);
			JLabel header = new JLabel("Edit Manuscript");
			header.setFont(new Font("Serif", Font.BOLD + Font.ITALIC, 22));
			JScrollPane pane = new JScrollPane(txt);


			grid.setLayout(new BorderLayout());
			grid.add(pane, BorderLayout.CENTER);
			grid.add(labels, BorderLayout.EAST);

			Border border = BorderFactory.createEmptyBorder(5, 5, 5, 5);
			main.setBorder(border);
			main.setPreferredSize(new Dimension(500, 400));
			main.setLayout(new BorderLayout());
			main.add(header, BorderLayout.NORTH);
			main.add(grid, BorderLayout.CENTER);

			add(main);
			pack();
		} //setup

		/**
		 * Sets up the labels for the JDialog.
		 * 
		 * @param buttons is the Container containing buttons.
		 * @return the container containing the top portion of the JDialog.
		 */
		private JPanel labels(Container buttons) {
			JPanel all = new JPanel();
			JPanel format = new JPanel();
			format.setLayout(new BorderLayout());
			all.setLayout(new BoxLayout(all, BoxLayout.Y_AXIS));
			Container titles = new JPanel(new FlowLayout(FlowLayout.LEADING));
			Container edited = new JPanel(new FlowLayout(FlowLayout.LEADING));
			Container wdc = new JPanel(new FlowLayout(FlowLayout.LEADING));

			JLabel lblCount = new JLabel("Word count: ");
			JLabel title = new JLabel("Title: " + paper.getTitle());
			revdate = new JLabel();
			words = new JLabel("" + count());

			//add 0 in front of single-digit minutes
			Calendar date = new GregorianCalendar();
			date.setTime(paper.getLatestRevision());
			int minute = date.get(Calendar.MINUTE);
			String min = "";
			if (minute < 10) {
				min = "0" + minute;
			} else {
				min = "" + minute;
			}

			//attach am/pm depending on the hour
			int hour = date.get(Calendar.HOUR_OF_DAY);
			String am_pm = "";
			if (hour > 12) {
				am_pm = "pm";
			} else {
				am_pm = "am";
			}

			revdate.setText("Last edited: " + date.get(Calendar.HOUR) + 
					":" + min + am_pm +
					" | " + (date.get(Calendar.MONTH) + 1) + 
					"/" + date.get(Calendar.DATE) + 
					"/" + date.get(Calendar.YEAR));

			titles.add(title);
			edited.add(revdate);
			wdc.add(lblCount);
			wdc.add(words);
			all.add(titles, BorderLayout.NORTH);
			all.add(edited, BorderLayout.CENTER);
			all.add(wdc, BorderLayout.SOUTH);
			format.add(all, BorderLayout.NORTH);
			format.add(buttons, BorderLayout.SOUTH);
			return format;
		} //labels

		/**
		 * Set up JTextArea with paper content and provide functions for editing.
		 * 
		 * @return JTextArea of the paper.
		 */
		private JTextArea displayContent() {
			area = new JTextArea(content);
			area.setEditable(true);
			area.setLineWrap(true);
			area.setWrapStyleWord(true);

			area.getDocument().addDocumentListener(new DocumentListener() {
				@Override
				public void changedUpdate(DocumentEvent e) {
					words.setText("" + count());
				} //changedUpdate

				@Override
				public void insertUpdate(DocumentEvent e) {
					words.setText("" + count());
				} //insertUpdate

				@Override
				public void removeUpdate(DocumentEvent e) {
					words.setText("" + count());
				} //removeUpdate
			});
			return area;
		} //displayContent

		/**
		 * Sets up the buttons and their listeners and store them into FlowLayout
		 * Container to be displayed on the JDialog.
		 * 
		 * @return the Container containing the buttons.
		 */
		private Container buttons() {
			Container flow = new JPanel(new FlowLayout(FlowLayout.CENTER));
			final JButton save = new JButton("Save");
			final JButton close = new JButton("Close");

			save.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (e.getSource() == save) {
						if (area.getText() != null) {
							text = area.getText().getBytes();
							paper.saveDigitalPaper(text);
							Calendar current = Calendar.getInstance();
							Date time = current.getTime();
							paper.setLatestRevision(time);
							
							//add 0 in front of single-digit minutes
							int minute = current.get(Calendar.MINUTE);
							String min = "";
							if (minute < 10) {
								min = "0" + minute;
							} else {
								min = "" + minute;
							}

							//attach am/pm to time depending on the hour
							int hour = current.get(Calendar.HOUR_OF_DAY);
							String am_pm = "";
							if (hour > 12) {
								am_pm = "pm";
							} else {
								am_pm = "am";
							}

							revdate.setText("Last edited: " + current.get(Calendar.HOUR) + 
									":" + min + am_pm +
									" | " + (current.get(Calendar.MONTH) + 1) + 
									"/" + current.get(Calendar.DATE) + 
									"/" + current.get(Calendar.YEAR));
							JOptionPane.showMessageDialog(null, "Paper " + paper.getTitle() + "saved!",
									"Select Manuscript", JOptionPane.INFORMATION_MESSAGE);
						}
					}
				}
			});

			close.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (e.getSource() == close) {
						text = area.getText().getBytes();
						paper.saveDigitalPaper(text);
						dispose();
					}
				}
			});

			flow.add(save);
			flow.add(close);
			return flow;
		} //buttons

		/**
		 * Counts the current words in the JTextArea.
		 * 
		 * @return the word count.
		 */
		private int count() {
			StringTokenizer st = new StringTokenizer(area.getText());
			return st.countTokens();
		} //count

		/**
		 * This is called from the SubmittedPapers tab in order to display the JDialog
		 * and to capture results when closing.
		 * 
		 * @param txt is the Byte[] representation of the contents in the paper.
		 */
		public void start(byte[] txt) {
			text = txt;
			
			addWindowListener(new WindowAdapter() {
				@Override
				public void windowClosing(WindowEvent e) {
					int result = JOptionPane.showConfirmDialog(null, 
							"Do you want to close the window without saving?", 
							"Closing", 
							JOptionPane.YES_NO_OPTION);
					
					if (result == JOptionPane.OK_OPTION) {
						Edit.this.dispose();
					}
				}
			});
			
			setModal(true);
			setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
			setLocationRelativeTo(null);
			setVisible(true);

		} //start
	} //Edit
	
	//================== Inner class: Save =========================//
	
	/**
	 * Gives user choices of where to save the file as well as what name they
	 * want to name the file.
	 * 
	 * @author Ching-Ting Huang
	 * @version UWTCSS 360, Spring 2013. 3-squared-software-systems.
	 */
	private class Save extends JDialog {
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 7987335874871014828L;
		private Paper paper;
		private JTextField fileName;
		private JTextField path;
		
		/**
		 * Initialize fields.
		 * 
		 * @param frame is the frame the JDialog will be centered on.
		 * @param title is the title of the JDialog.
		 * @param p is the currently selected paper.
		 */
		private Save(JFrame frame, String title, Paper p) {
			super(frame, title);
			paper = p;
			setup();
		} //Save
		
		/**
		 * Sets up the looks of the JDialog.
		 */
		private void setup() {
			JPanel main = new JPanel();
			JPanel rest = new JPanel();
			Container name = fileName();
			Container dir = directory();
			Container btn = new JPanel(new FlowLayout(FlowLayout.CENTER));
			final JButton confirm = new JButton("Confirm");
			Border border = BorderFactory.createTitledBorder("Save Manuscript");
			main.setBorder(border);
			
			confirm.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (e.getSource() == confirm) {
						String dir = path.getText();
						String fn = fileName.getText();
						
						if (dir.length() != 0 && fn.length() != 0) {
							//forcing the file to save as a .txt file
							if (!fn.substring(fn.length() - 5, fn.length() - 1).equals(".txt")) {
								fn = fn + ".txt";
							}
							String text = null;
							try {
								text = new String(paper.loadDigitalPaper(), "UTF-8");
							} catch (UnsupportedEncodingException e2) {
								e2.printStackTrace();
							}
							
							try {
								//write to file with user specified file name & path
								File file = new File(dir, fn);
								BufferedWriter bw = new BufferedWriter(new FileWriter(file));
								if (text != null) {
									StringTokenizer st = new StringTokenizer(text);
									while (st.hasMoreTokens()) {
										bw.write(st.nextToken());
										bw.write(" ");
									}
									bw.flush();
									bw.close();
								}
							} catch (IOException e1) {
								e1.printStackTrace();
							}
							JOptionPane.showMessageDialog(null, 
									"File successfully saved at: " + dir + " !", 
									"Closing", 
									JOptionPane.PLAIN_MESSAGE);
							Save.this.dispose();
						} else if (fn.length() == 0) {
							JOptionPane.showMessageDialog(null, 
									"Please give the file a name.", 
									"File Name", 
									JOptionPane.ERROR_MESSAGE);
						} else if (dir.length() == 0) {
							JOptionPane.showMessageDialog(null, 
									"Please indicate a path for the file.", 
									"File Path", 
									JOptionPane.ERROR_MESSAGE);
						}
					}
				} //actionPerformed
			});
			
			btn.add(confirm);
			
			rest.setLayout(new BorderLayout());
			rest.add(name, BorderLayout.NORTH);
			rest.add(dir, BorderLayout.CENTER);
			
			main.setLayout(new BorderLayout());
			main.add(rest, BorderLayout.CENTER);
			main.add(btn, BorderLayout.SOUTH);
			add(main);
			pack();
		} //setup
		
		/**
		 * Sets up the looks for the file name input.
		 * 
		 * @return Container containing both label and text field.
		 */
		private Container fileName() {
			Container flow = new JPanel(new FlowLayout(FlowLayout.LEADING));
			JLabel lblName = new JLabel("File Name:");
			fileName = new JTextField("*.txt",20);
			fileName.setEditable(true);
			flow.add(lblName);
			flow.add(fileName);
			return flow;
		} //fileName
		
		/**
		 * Sets up the JTextField to pull up JFileChooser for the user to choose
		 * the path they wanted the file saved as well setting up the label.
		 * 
		 * @return Container containing the label and text field.
		 */
		private Container directory() {
			Container flow = new JPanel(new FlowLayout(FlowLayout.LEADING));
			JLabel lblDir = new JLabel("Directory: ");
			path = new JTextField(20);
			path.setEditable(false);
			
			path.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					JFileChooser fc = new JFileChooser();
					fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
					int result = fc.showSaveDialog(SubmittedPapers.this);
					if (result == JFileChooser.APPROVE_OPTION) {
						path.setText(fc.getSelectedFile().getAbsolutePath());
					}
				} //mouseClicked
			});
			
			flow.add(lblDir);
			flow.add(path);
			return flow;
		} //directory
		
		/**
		 * Sets up miscellaneous settings for the JDialog and make it visible
		 * when this method is called.
		 */
		public void start() {
			setModal(true);
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			setLocationRelativeTo(null);
			setVisible(true);
		} //start
	} //Save
} //outer
